<template>
  <div class="screen-share-container">
    <h1>WebRTC 原生屏幕共享测试</h1>

    <div class="control-panel">
      <div class="input-group">
        <button @click="startSharing" :disabled="isSharing">开始共享</button>
        <button @click="stopSharing" :disabled="!isSharing">停止共享</button>
      </div>

      <div class="sdp-exchange">
        <!-- 本地 Offer 区域 -->
        <div class="sdp-box">
          <h3>本地 Offer</h3>
          <textarea v-model="localOffer" readonly></textarea>
          <button @click="copyLocalOffer" :disabled="!localOffer">复制</button>
          <button @click="createOffer" :disabled="!isSharing">生成 Offer</button>
        </div>

        <!-- 远程 Offer 区域 -->
        <div class="sdp-box">
          <h3>远程 Offer</h3>
          <textarea v-model="remoteOffer" placeholder="粘贴远程 Offer 这里"></textarea>
          <button @click="setRemoteOffer" :disabled="!remoteOffer">设置 Offer</button>
          <button @click="createAnswer" :disabled="!hasRemoteOffer">生成 Answer</button>
        </div>

        <!-- 远程 Answer 区域 -->
        <div class="sdp-box">
          <h3>远程 Answer</h3>
          <textarea v-model="remoteAnswer" placeholder="粘贴远程 Answer 这里"></textarea>
          <button @click="setRemoteAnswer" :disabled="!remoteAnswer">设置 Answer</button>
        </div>

        <!-- 本地 ICE Candidates 区域 -->
        <div class="sdp-box">
          <h3>本地 ICE Candidates</h3>
          <textarea v-model="localCandidates" readonly></textarea>
          <button @click="copyLocalCandidates" :disabled="!localCandidates">复制</button>
        </div>

        <!-- 远程 ICE Candidates 区域 -->
        <div class="sdp-box">
          <h3>远程 ICE Candidates</h3>
          <textarea v-model="remoteCandidates" placeholder="粘贴远程 ICE Candidates 这里"></textarea>
          <button @click="addRemoteCandidates" :disabled="!remoteCandidates">添加 Candidates</button>
        </div>
      </div>
    </div>

    <div class="video-container">
      <div class="video-box">
        <h3>本地屏幕</h3>
        <video ref="localVideo" autoplay muted playsinline></video>
      </div>
      <div class="video-box">
        <h3>远程视频</h3>
        <video ref="remoteVideo" autoplay playsinline></video>
      </div>
    </div>

    <div class="status">
      <p>状态: {{ status }}</p>
      <p v-if="error" class="error">错误: {{ error }}</p>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, onBeforeUnmount } from 'vue';

export default defineComponent({
  name: 'NativeScreenShare',
  setup() {
    const isSharing = ref<boolean>(false);
    const status = ref<string>('准备就绪');
    const error = ref<string>('');

    const localVideo = ref<HTMLVideoElement | null>(null);
    const remoteVideo = ref<HTMLVideoElement | null>(null);

    // SDP 和 ICE 交换相关
    const localOffer = ref<string>('');
    const remoteOffer = ref<string>('');
    const remoteAnswer = ref<string>('');
    const localCandidates = ref<string>('');
    const remoteCandidates = ref<string>('');
    const hasRemoteOffer = ref<boolean>(false);

    let localStream: MediaStream | null = null;
    let peerConnection: RTCPeerConnection | null = null;

    // 创建 PeerConnection
    const createPeerConnection = () => {
      const configuration: RTCConfiguration = {
        iceServers: [
          { urls: 'stun:stun.l.google.com:19302' },
          // 如果需要，可以添加 TURN 服务器
          // { urls: 'turn:your.turn.server', username: 'user', credential: 'pass' }
        ]
      };

      peerConnection = new RTCPeerConnection(configuration);

      // 添加本地流
      if (localStream) {
        localStream.getTracks().forEach(track => {
          peerConnection?.addTrack(track, localStream as MediaStream);
        });
      }

      // ICE candidate 收集
      peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
          const candidate = JSON.stringify(event.candidate);
          localCandidates.value += candidate + '\n';
          status.value = '收集到新的 ICE candidate';
        } else {
          status.value = 'ICE candidate 收集完成';
        }
      };

      // 远程流到达
      peerConnection.ontrack = (event) => {
        if (remoteVideo.value && event.streams && event.streams[0]) {
          remoteVideo.value.srcObject = event.streams[0];
          status.value = '接收到远程流';
        }
      };

      // 连接状态变化
      peerConnection.oniceconnectionstatechange = () => {
        if (peerConnection) {
          const state = peerConnection.iceConnectionState;
          status.value = `ICE 连接状态: ${state}`;

          if (state === 'connected' || state === 'completed') {
            status.value = 'WebRTC 连接成功!';
          } else if (state === 'failed') {
            error.value = 'ICE 连接失败';
          }
        }
      };
    };

    // 开始屏幕共享
    const startSharing = async () => {
      try {
        status.value = '正在获取屏幕共享...';
        localStream = await navigator.mediaDevices.getDisplayMedia({
          video: true,
          audio: false
        });

        if (localVideo.value) {
          localVideo.value.srcObject = localStream;
          isSharing.value = true;
          status.value = '屏幕共享已开始';
          console.log(peerConnection)
          // 创建 PeerConnection
          createPeerConnection();
          console.log(peerConnection)
        }
      } catch (err) {
        error.value = `无法获取屏幕共享: ${err instanceof Error ? err.message : String(err)}`;
        console.error('Screen share error:', err);
      }
    };

    // 停止屏幕共享
    const stopSharing = () => {
      if (localStream) {
        localStream.getTracks().forEach(track => track.stop());
        localStream = null;
      }

      if (localVideo.value) {
        localVideo.value.srcObject = null;
      }

      if (peerConnection) {
        peerConnection.close();
        peerConnection = null;
      }

      isSharing.value = false;
      localOffer.value = '';
      remoteOffer.value = '';
      remoteAnswer.value = '';
      localCandidates.value = '';
      remoteCandidates.value = '';
      hasRemoteOffer.value = false;
      status.value = '屏幕共享已停止';
    };

    // 创建 Offer
    const createOffer = async () => {
      if (!peerConnection) {
        error.value = 'PeerConnection 未初始化';
        return;
      }

      try {
        status.value = '正在创建 Offer...';
        const offer = await peerConnection.createOffer();
        await peerConnection.setLocalDescription(offer);

        // 等待 ICE candidates 收集
        await new Promise<void>((resolve) => {
          const checkInterval = setInterval(() => {
            if (peerConnection?.iceGatheringState === 'complete') {
              clearInterval(checkInterval);
              resolve();
            }
          }, 100);
        });

        localOffer.value = JSON.stringify(peerConnection.localDescription);
        status.value = 'Offer 创建完成';
      } catch (err) {
        error.value = `创建 Offer 失败: ${err instanceof Error ? err.message : String(err)}`;
        console.error('Create offer error:', err);
      }
    };

    // 设置远程 Offer
    const setRemoteOffer = async () => {
      if (!peerConnection) {
        error.value = 'PeerConnection 未初始化';
        return;
      }

      try {
        status.value = '正在设置远程 Offer...';
        const offer = JSON.parse(remoteOffer.value);
        await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
        hasRemoteOffer.value = true;
        status.value = '远程 Offer 设置成功';
      } catch (err) {
        error.value = `设置 Offer 失败: ${err instanceof Error ? err.message : String(err)}`;
        console.error('Set offer error:', err);
      }
    };

    // 创建 Answer
    const createAnswer = async () => {
      if (!peerConnection || !hasRemoteOffer.value) {
        error.value = '请先设置远程 Offer';
        return;
      }

      try {
        status.value = '正在创建 Answer...';
        console.log(peerConnection)
        const answer = await peerConnection.createAnswer();
        await peerConnection.setLocalDescription(answer);

        // 等待 ICE candidates 收集
        await new Promise<void>((resolve) => {
          const checkInterval = setInterval(() => {
            if (peerConnection?.iceGatheringState === 'complete') {
              clearInterval(checkInterval);
              resolve();
            }
          }, 100);
        });

        remoteAnswer.value = JSON.stringify(peerConnection.localDescription);
        status.value = 'Answer 创建完成';
      } catch (err) {
        error.value = `创建 Answer 失败: ${err instanceof Error ? err.message : String(err)}`;
        console.error('Create answer error:', err);
      }
    };

    // 设置远程 Answer
    const setRemoteAnswer = async () => {
      if (!peerConnection) {
        error.value = 'PeerConnection 未初始化';
        return;
      }

      try {
        status.value = '正在设置远程 Answer...';
        const answer = JSON.parse(remoteAnswer.value);
        await peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
        status.value = '远程 Answer 设置成功';
      } catch (err) {
        error.value = `设置 Answer 失败: ${err instanceof Error ? err.message : String(err)}`;
        console.error('Set answer error:', err);
      }
    };

    // 添加远程 ICE Candidates
    const addRemoteCandidates = async () => {
      if (!peerConnection) {
        error.value = 'PeerConnection 未初始化';
        return;
      }

      try {
        status.value = '正在添加远程 ICE candidates...';
        const candidates = remoteCandidates.value.trim().split('\n');

        for (const candidateStr of candidates) {
          if (candidateStr.trim()) {
            const candidate = JSON.parse(candidateStr);
            await peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
          }
        }

        status.value = `已添加 ${candidates.length} 个远程 ICE candidates`;
      } catch (err) {
        error.value = `添加 ICE candidates 失败: ${err instanceof Error ? err.message : String(err)}`;
        console.error('Add ICE candidates error:', err);
      }
    };

    // 复制文本到剪贴板
    const copyToClipboard = (text: string) => {
      navigator.clipboard.writeText(text).then(() => {
        status.value = '已复制到剪贴板';
      }).catch(err => {
        error.value = `复制失败: ${err instanceof Error ? err.message : String(err)}`;
      });
    };

    const copyLocalOffer = () => {
      if (localOffer.value) {
        copyToClipboard(localOffer.value);
      }
    };

    const copyLocalCandidates = () => {
      if (localCandidates.value) {
        copyToClipboard(localCandidates.value);
      }
    };

    // 组件卸载时清理
    onBeforeUnmount(() => {
      stopSharing();
    });

    return {
      isSharing,
      status,
      error,
      localVideo,
      remoteVideo,
      localOffer,
      remoteOffer,
      remoteAnswer,
      localCandidates,
      remoteCandidates,
      hasRemoteOffer,
      startSharing,
      stopSharing,
      createOffer,
      setRemoteOffer,
      createAnswer,
      setRemoteAnswer,
      addRemoteCandidates,
      copyLocalOffer,
      copyLocalCandidates
    };
  }
});
</script>

<style scoped>
.screen-share-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.control-panel {
  background-color: #f5f5f5;
  padding: 15px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.input-group {
  margin-bottom: 10px;
}

.sdp-exchange {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 20px;
}

.sdp-box {
  background-color: #fff;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 15px;
}

.sdp-box h3 {
  margin-top: 0;
  margin-bottom: 10px;
}

.sdp-box textarea {
  width: 100%;
  height: 150px;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  resize: vertical;
  margin-bottom: 10px;
  font-family: monospace;
}

.sdp-box button {
  padding: 8px 15px;
  margin-right: 10px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.sdp-box button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

.video-container {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}

.video-box {
  flex: 1;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 10px;
  background-color: #f9f9f9;
}

.video-box h3 {
  margin-top: 0;
  text-align: center;
}

video {
  width: 100%;
  max-height: 400px;
  background-color: #000;
  border-radius: 4px;
}

.status {
  padding: 10px;
  background-color: #f0f0f0;
  border-radius: 4px;
}

.error {
  color: red;
}
</style>
